/*
 * This file is part of quickReminder, a software for gamers
 *
 * Copyright (C) 2006-2008 Lucas Romero
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;

using System.Text.RegularExpressions;
using HtmlAgilityPack;
using System.Threading;
using System.Diagnostics;
using System.IO;
using UserNotifier;
using Meebey.SmartIrc4net;

namespace quickReminder
{
    public partial class FormChallenger : Form
    {
        IrcClient m_IRC = new IrcClient();
        System.Threading.Timer refresher;
        bool m_Running = false;
        private CookieContainer cookies = new CookieContainer();
        private string league = "/de/dota/2on2/ladder/instantchallenge/start/?trusted=0&elorange=all";
        private string lid = string.Empty;
        private string m_Matchlink = string.Empty;
        private DateTime m_DueTime = DateTime.MinValue;
        private DateTime m_LastDueDate = DateTime.MinValue;
        private HWBeepWarnModule beeper = new HWBeepWarnModule(1000, 500, 200);
        string viewformat = @"<table height=""100%"" width=""100%""><tr><td align=""center"" valign=""center"" style=""font-family: Verdana, Tahoma"">{0}</td></tr></table>";

        public FormChallenger()
        {
            InitializeComponent();
            m_IRC.OnJoin += new JoinEventHandler(m_IRC_OnJoin);
            m_IRC.OnConnected += new EventHandler(m_IRC_OnConnected);
            m_IRC.OnChannelMessage += new IrcEventHandler(m_IRC_OnChannelMessage);
            m_IRC.OnConnectionError += new EventHandler(m_IRC_OnConnectionError);
            m_IRC.OnError += new Meebey.SmartIrc4net.ErrorEventHandler(m_IRC_OnError);
            //m_IRC.OnErrorMessage += new IrcEventHandler(m_IRC_OnErrorMessage);

            Control.CheckForIllegalCrossThreadCalls = false;
            
            //m_IRC.WriteLine(m_IRCPerformString);




            IrcThread = new Thread(new ThreadStart(IrcMain));
            IrcThread.IsBackground = true;
            IrcThread.Start();
            
        }
        Thread IrcThread;
        void IrcMain()
        {
            m_IRC.Encoding = System.Text.Encoding.UTF8;

            // wait time between messages, we can set this lower on own irc servers
            m_IRC.SendDelay = 200;

            // we use channel sync, means we can use irc.GetChannel() and so on
            m_IRC.ActiveChannelSyncing = false;
            m_IRC.Connect("irc.esl-europe.net", 6667);
            m_IRC.Login("qrClient", "quickReminder user");
            m_IRC.RfcJoin("#quickReminder");
            m_IRC.Listen();
            
        }

        void m_IRC_OnJoin(object sender, JoinEventArgs e)
        {
            MessageBox.Show(e.Data.RawMessage);
        }

        void m_IRC_OnErrorMessage(object sender, IrcEventArgs e)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        void m_IRC_OnError(object sender, Meebey.SmartIrc4net.ErrorEventArgs e)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        void m_IRC_OnConnectionError(object sender, EventArgs e)
        {
            throw new Exception("The method or operation is not implemented.");
        }
        delegate void OnChannelMessageDelegate(object sender, IrcEventArgs e);
        void m_IRC_OnChannelMessage(object sender, IrcEventArgs e)
        {
            if (rtbChat.InvokeRequired)
            {
                rtbChat.Invoke(new OnChannelMessageDelegate(m_IRC_OnChannelMessage), new object[] { sender, e });
                return;
            }
            rtbChat.AppendText(String.Format("[{0}] {1}:\t{2}\n",DateTime.Now.ToShortTimeString(), e.Data.Nick, e.Data.Message));
            rtbChat.ScrollToCaret();
        }

        private void AddFormattedChatString(string s)
        {
            AddFormattedChatString(s, rtbChat.ForeColor, false);
        }
        private void AddFormattedChatString(string s, Color color)
        {
            AddFormattedChatString(s, color, false);
        }

        private void AddFormattedChatString(string s, Color color, bool bold)
        {
            RichTextBox log = rtbChat;
            int start = log.Text.Length;
            int selstart = log.SelectionStart;
            int sellength = log.SelectionLength;
            log.AppendText(s + Environment.NewLine);
            //log.Text += s + Environment.NewLine;
            //log.SelectionStart = start;
            //log.SelectionLength = s.Length;
            log.Select(start, s.Length);

            log.SelectionColor = color;
            FontStyle style = FontStyle.Regular;

            if (bold)
                style = FontStyle.Bold;
            Font f = new Font(log.Font.FontFamily, log.Font.SizeInPoints, style);
            log.SelectionFont = f;
            //log.Select(start, s.Length);
            log.Select(selstart, sellength);
        }

        //string m_IRCChannelName;
        //string m_IRCChannelPassword;
        string m_IRCPerformString;
        void m_IRC_OnConnected(object sender, EventArgs e)
        {
            return;
            m_IRC.Login("qrClient", "quickReminder user");
            //m_IRC.ListenOnce();
           
            m_IRC.RfcJoin("#quickReminder");
            //m_IRC.ListenOnce();
            m_IRC.WriteLine(m_IRCPerformString);
            //m_IRC.ListenOnce();
        }

        private void FormChallenger_Shown(object sender, EventArgs e)
        {
            return;
            using (FormChallengeSetup f = new FormChallengeSetup())
            {
                if (f.ShowDialog() == DialogResult.OK)
                {
                    league = f.Challenge;
                    Start();
                }
                else
                    this.Close();
            }
            //Start();
        }
        
        private void Start()
        {
            m_Running = true;
            refresher = new System.Threading.Timer(new TimerCallback(InitSearch), league, 0, Timeout.Infinite);
            //InitSearch(league);
        }

        private void InitSearch(object url)
        {
            InitSearch((string)url);
        }

        private void InitSearch(string url)
        {
            if (!m_Running)
                return;
            trayIcon.Icon = lang.enemysearch16;
            this.Icon = lang.enemysearch16;
            string HTML = GetHTML(@"http://www.esl.eu" + url, Properties.Settings.Default.Cookie);
            string pattern = @"(/interface/instantchallenger/start\.html\?t=(\d+)&lid=(\d+))";
            Match m = Regex.Match(HTML, pattern);
            if (m.Success)
            {
                Debug.WriteLine("Found startlink, starting now...");
                lid = m.Groups[2].Value;
                trayIcon.Visible = true;
                webBrowser1.DocumentText = String.Format(viewformat, "<h2>Searching ...</h2>");
                if (m_Running)
                    ParseESLPage(m.Value);
            }
            else
            {
                HtmlAgilityPack.HtmlDocument d = new HtmlAgilityPack.HtmlDocument();
                d.LoadHtml(HTML);
                string activeexists = @"//div[text()=""An active search has been started, what would you like to do?""]/a[text()=""Continue searching""]";
                HtmlNode activeexistsnode = d.DocumentNode.SelectSingleNode(activeexists);
                HtmlNode searchexistsnode = d.DocumentNode.SelectSingleNode(@"//div[text()=""You are still having open Instant Challenger Matches, are you sure that you want to search for a new match?""]");
                if (activeexistsnode != null)
                {
                    Debug.WriteLine("An active search was found, restarting ...");
                    if (m_Running)
                        InitSearch(activeexistsnode.Attributes["href"].Value);
                }
                else if (searchexistsnode != null)
                {
                    if (m_Running && MessageBox.Show("You still have open Instant Challenger matches, do you really want to start a new search?", "Matches open", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        InitSearch(url + "&verify=t");
                }
                else
                {
                    Debug.WriteLine("Damn, got up on the wrong foot, don't know where to start!");
                    trayIcon.ShowBalloonTip(5000, "Error", "Parse error, could not start search", ToolTipIcon.Error);
                    webBrowser1.DocumentText = StripGarbage(HTML);
                }

            }
        }

        private void ParseESLPage(object url)
        {
            ParseESLPage((string)url);
        }

        delegate void UpdateProgressValueDelegate(int value);
        private void UpdateProgressValue(int value)
        {
            if (InvokeRequired)
            {
                Invoke(new UpdateProgressValueDelegate(UpdateProgressValue), new object[] { value });
                return;
            }
            pbTimer.Value = value;
        }

        delegate void UpdateProgressMaximumDelegate(int value);
        private void UpdateProgressMaximum(int value)
        {
            if (InvokeRequired)
            {
                Invoke(new UpdateProgressMaximumDelegate(UpdateProgressMaximum), new object[] { value });
                return;
            }
            pbTimer.Maximum = value;
        }

        delegate void UpdateProgressStyleDelegate(ProgressBarStyle value);
        private void UpdateProgressStyle(ProgressBarStyle value)
        {
            if (InvokeRequired)
            {
                Invoke(new UpdateProgressStyleDelegate(UpdateProgressStyle), new object[] { value });
                return;
            }
            pbTimer.Style = value;
        }

        private void UpdateProgressMaximum()
        {

        }

        private void ParseESLPage(string url)
        {
            if (!m_Running)
                return;
            //Debug.WriteLine("Parsing " + url);
            string HTML = GetHTML(@"http://www.esl.eu" + url, Properties.Settings.Default.Cookie);
            HtmlAgilityPack.HtmlDocument d = new HtmlAgilityPack.HtmlDocument();
            d.LoadHtml(HTML);
            string nexturl = @"<meta http-equiv=""refresh"" content=""(\d+); URL=(.*?)"">";
            Match refresh = Regex.Match(HTML, nexturl);
            if (refresh.Success)
            {
                //tTimer.Stop();
                int duetime = int.Parse(refresh.Groups[1].Value) * 1000;
                
                Debug.WriteLine("Found meta refresh instruction: refreshing in " + duetime + " ms.");
                
                //tTimer.Start();
                if (m_Running)
                    refresher = new System.Threading.Timer(new TimerCallback(ParseESLPage), refresh.Groups[2].Value, duetime, Timeout.Infinite);
                
                //trayIcon.ShowBalloonTip(1000, "Performing search", "Run " + Text, ToolTipIcon.Info);
                if (!this.IsDisposed)
                {
                    if (d.DocumentNode.SelectSingleNode(@"//div/b[text()=""Next opponent assignment""]/../following-sibling::div/b/text()") != null)
                    {
                        
                        /*pbTimer.Style = ProgressBarStyle.Marquee;
                        pbTimer.Value = 10;
                        pbTimer.Maximum = 100;*/
                        string duedatestr = d.DocumentNode.SelectSingleNode(@"//div/b[text()=""Next opponent assignment""]/../following-sibling::div/b/text()").InnerText.Trim();
                        DateTime duedate = DateTime.Parse(duedatestr.Substring(duedatestr.IndexOf(' ')+1, duedatestr.Length - (duedatestr.IndexOf(' ')+1)));
                        TimeSpan remaining = duedate.Subtract(DateTime.Now);
                        //Text = "Next assignment: " + duedate.ToString();
                        Text =
                            String.Format("{0:00}:{1:00}:{2:00}", (int)remaining.TotalHours, remaining.Minutes, remaining.Seconds) +
                            " remaining till next assignment";
                        if (m_LastDueDate != DateTime.MinValue)
                        {
                            UpdateProgressMaximum((int)duedate.Subtract(m_LastDueDate).TotalMilliseconds);
                            UpdateProgressValue((int)DateTime.Now.Subtract(m_LastDueDate).TotalMilliseconds);
                            UpdateProgressStyle(ProgressBarStyle.Continuous);
                        }
                        else
                            UpdateProgressStyle(ProgressBarStyle.Marquee);
                    }
                    else
                    {
                        m_DueTime = DateTime.Now.AddMilliseconds(duetime);
                        UpdateProgressStyle(ProgressBarStyle.Blocks);
                        UpdateProgressMaximum(duetime);
                        pbTimer.Step = tTimer.Interval;
                        UpdateProgressValue(0);
                        string progress = d.DocumentNode.SelectSingleNode("html/body/table/tr/td/table/tr/td/table/tr/td").InnerText;
                        Text = progress + " - Searching";
                    }
                    
                    //webBrowser1.DocumentText =
                        //StripGarbage(String.Format(viewformat, d.DocumentNode.SelectSingleNode("html/body/table/tr/td/table/tr/td/table").WriteTo()));
                }
            }
            else
            {
                HTML = StripGarbage(HTML);
                string continuesearch = @"//a[text()=""Continue Searching""]";
                string newsearch = @"//a[text()=""Start new search""]";
                HtmlNode newsearchnode = d.DocumentNode.SelectSingleNode(newsearch);
                HtmlNode continuesearchnode = d.DocumentNode.SelectSingleNode(continuesearch);
                HtmlNode nosearchnode = d.DocumentNode.SelectSingleNode(@"//div/b[text()=""No active search exists. Please close this window and start a new Instant Challenger search, if you have no open matches!""]");
                if (newsearchnode != null)
                {
                    Debug.WriteLine("An active search was found, restarting ...");
                    if (!this.IsDisposed)
                        trayIcon.ShowBalloonTip(5000, "Active search exists", "Started new search", ToolTipIcon.Info);
                    InitSearch(newsearchnode.Attributes["href"].Value);
                }
                else if (continuesearchnode != null)
                {
                    string continueurl = continuesearchnode.Attributes["href"].Value;
                    if (continueurl.EndsWith("/search/"))
                    {
                        Debug.WriteLine("An active search was found, resuming ...");
                        if (!this.IsDisposed)
                            trayIcon.ShowBalloonTip(5000, "Active search exists", "Resumed active search", ToolTipIcon.Info);
                        InitSearch(continueurl);
                    }
                    else
                    {
                        Debug.WriteLine("Continueing search ...");
                        //if (!this.IsDisposed)
                            //trayIcon.ShowBalloonTip(5000, "Continuing search", "No opponent could be found, searching on", ToolTipIcon.Info);
                        ParseESLPage(continueurl);
                    }
                }
                else if (nosearchnode != null)
                {
                    Text = "Search aborted";
                    //string viewformat = @"<table height=""100%"" width=""100%""><tr><td align=""center"" valign=""center"" style=""font-family: Verdana, Tahoma"">{0}</td></tr></table>";
                    webBrowser1.DocumentText = String.Format(viewformat, "<h2>Search aborted ...</h2>");
                }
                else if(d.DocumentNode.SelectSingleNode(@"html/head/title[text()=""ESL Pre-Match""]") != null)
                {
                    trayIcon.Icon = lang.enemyfound16;
                    this.Icon = lang.enemyfound16;
                    HtmlNode data = d.DocumentNode.SelectSingleNode(@"html/body/table/tr/td/table/tr/td/b[text()=""Opponent""]/../../..");
                    string enemy = d.DocumentNode.SelectSingleNode(@"//a[text()=""View Teamsheet""]//preceding-sibling::div").InnerText.Trim();
                    HtmlNodeCollection infos = d.DocumentNode.SelectNodes(@"//a[text()=""View Teamsheet""]//following-sibling::table/tr[position()>1]");
                    string infostr = string.Empty;
                    foreach (HtmlNode n in infos)
                        infostr += n.InnerText.Trim() + Environment.NewLine;
                    infostr = infostr.Trim();
                    m_Matchlink = d.DocumentNode.SelectSingleNode(@"//a[text()=""Matchdetails""]").Attributes["href"].Value;
                    //HtmlNode data = opponent.ParentNode.ParentNode.Pa;
                    /*string enemy = data.SelectSingleNode("tr/td/div/div/b").InnerText;
                    string rank = data.SelectSingleNode(@"tr/td/div/table/tr/td[text()=""Rank:""]/../td[2]").InnerText;
                    string points = data.SelectSingleNode(@"tr/td/div/table/tr/td[text()=""Points:""]/../td[2]").InnerText;
                    string stats = data.SelectSingleNode(@"tr/td/div/table/tr/td[text()=""Matches:""]/../td[2]").InnerText;*/
                    //string parameters = data.SelectSingleNode(@"//table/tr/td/div/div/div[text()=""Parameter""]/../td[2]").InnerText;
                    string text = String.Format("Opponent found: {0}\n{1}\n\nClick here for details", enemy, infostr);
                    if (!this.IsDisposed)
                    {
                        Text = "Generated match against " + enemy;
                        trayIcon.BalloonTipClicked += new EventHandler(trayIcon_BalloonTipClicked);
                        trayIcon.ShowBalloonTip(60000, "Opponent found!", text, ToolTipIcon.Info);
                        
                    }
                    m_IRCPerformString = d.DocumentNode.SelectSingleNode(@"//applet/param[@name=""command1""]").Attributes["value"].Value;
                    /*m_IRC.NicknameList = new string[] {
                        d.DocumentNode.SelectSingleNode(@"//applet/param[@name=""nick""]").Attributes["value"].Value,
                        d.DocumentNode.SelectSingleNode(@"//applet/param[@name=""alternatenick""]").Attributes["value"].Value
                    };*/
                    m_IRC.Connect(d.DocumentNode.SelectSingleNode(@"//applet/param[@name=""host""]").Attributes["value"].Value, 6667);

                }
                else
                {
                    HtmlNode titlenode = d.DocumentNode.SelectSingleNode("//head/title");
                    HtmlNode bodynode = d.DocumentNode.SelectSingleNode("//html/body");
                    string title = "Error!";
                    string message ="Could not parse content";
                    if (titlenode != null)
                        title = titlenode.InnerText;
                    if (bodynode != null)
                        message = bodynode.InnerText.Trim();
                    if (!this.IsDisposed)
                        trayIcon.ShowBalloonTip(5000, title, message, ToolTipIcon.Error);
                    //trayIcon.Visible = false;
                    if (!this.IsDisposed)
                    {
                        Text = "Error!";
                        webBrowser1.DocumentText = HTML;
                    }
                }
                
            }
        }

        void trayIcon_BalloonTipClicked(object sender, EventArgs e)
        {
            trayIcon.BalloonTipClicked -= new EventHandler(trayIcon_BalloonTipClicked);
            Process.Start("http://www.esl.eu" + m_Matchlink);
        }

        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            WebBrowser b = sender as WebBrowser;
            //b.DocumentText
        }

        private string StripGarbage(string html)
        {
            HtmlAgilityPack.HtmlDocument d = new HtmlAgilityPack.HtmlDocument();
            d.LoadHtml(html);
            HtmlNode main = d.DocumentNode.SelectSingleNode(@"/html/body/div/div/div[@id=""page""]/div[@id=""main""]/div[@id=""col3""]/div[@id=""col3_content""]/div[@id=""main_content""]");
            if (main != null)
                return main.WriteTo();
            string nexturl = @"<meta http-equiv=""refresh"" content=""(\d+); URL=(.*?)"">";
            Match refresh = Regex.Match(html, nexturl);
            if (refresh.Success)
                html = html.Replace(refresh.Value, "");
            html = Regex.Replace(html, @"<script type=""text/javascript"">.*?</script>", "", RegexOptions.Singleline);
            return html;
        }

        public string GetHTML(string URL)
        {
            return GetHTML(URL, Properties.Settings.Default.Cookie);
        }
        public string GetHTML(string URL, string cook)
        {
            return GetHTML(URL, new Cookie("COOKIE", cook, "/", ".esl.eu"));
        }
        public string GetHTML(string URL, Cookie cook)
        {
            URL = URL.Replace("&amp;", "&");
            Debug.WriteLine("HTTP GET: " + URL);
            string HTML = String.Empty;
            HttpWebRequest request;
            HttpWebResponse response;
            StreamReader answer = null;
            request = (HttpWebRequest)WebRequest.Create(URL);
            request.Timeout = 10000;
            request.CookieContainer = cookies;
            request.CookieContainer.Add(cook);
            //get response

            try
            {
                response = (HttpWebResponse)request.GetResponse();
                answer = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
                //while (m_UploadStatus != ItemUploadStatus.Aborted && answer.ReadLine() != String.Empty)
                //{
                //HTML += answer.ReadLine();
                //}
                HTML = answer.ReadToEnd();
                cookies = new CookieContainer();
                cookies.Add(response.Cookies);
                StreamWriter s = new StreamWriter(String.Format("dump{0}.txt", logcount++));
                s.Write(HTML);
                s.Close();
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.Timeout)
                    return "Timeout! ESL offline?";
                else
                    return "WebException!";
            }
            catch (IOException)
            {
                //i dont care about IO!
            }
            finally
            {
                if (answer != null)
                    answer.Close();
            }
            return HTML;
        }
        private int logcount = 0;
        private void tsbRestart_Click(object sender, EventArgs e)
        {
            //StartSearch("/de/dota/2on2/ladder/instantchallenge/start/?trusted=0&elorange=all");
            //StartSearch("/de/cs/2on2/ladder/instantchallenge/start/?trusted=0&elorange=all&parameter[1829]=de_nuke&hasserver=false");
            m_Running = false;
            if (refresher != null)
                refresher.Change(Timeout.Infinite, Timeout.Infinite);
            Start();
        }

        private void tsbCancel_Click(object sender, EventArgs e)
        {
            m_Running = false;
            m_DueTime = DateTime.MinValue;
            UpdateProgressStyle(ProgressBarStyle.Blocks);
            UpdateProgressValue(0);
            if (refresher != null)
                refresher.Change(Timeout.Infinite, Timeout.Infinite);
            Text = "Search aborting";
            webBrowser1.DocumentText = String.Format(viewformat, "<h2>Aborting search...</h2>");
            string HTML = GetHTML("http://www.esl.eu/interface/instantchallenger/start.html?action=cancel&lid=" + lid);
            HtmlAgilityPack.HtmlDocument d = new HtmlAgilityPack.HtmlDocument();
            d.LoadHtml(HTML);
            HtmlNode nosearchnode = d.DocumentNode.SelectSingleNode(@"//div/b[text()=""No active search exists. Please close this window and start a new Instant Challenger search, if you have no open matches!""]");
            if (nosearchnode != null)
            {
                Text = "Search aborted";
                
                webBrowser1.DocumentText = String.Format(viewformat, "<h2>Search aborted</h2>");
            }
            else
            {
                webBrowser1.DocumentText = StripGarbage(HTML);
            }
        }

        private void FormChallenger_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (refresher != null)
                tsbCancel_Click(this, e);
            m_IRC.RfcQuit("Instant Challenger powered by quickReminder - www.enterprising-developers.de");
        }

        private void tTimer_Tick(object sender, EventArgs e)
        {
            if (pbTimer.Style == ProgressBarStyle.Marquee)
                return;
            if (DateTime.Now > m_DueTime)
                pbTimer.Value = pbTimer.Maximum;
            else
            {
                int elapsed = pbTimer.Maximum - (int)m_DueTime.Subtract(DateTime.Now).TotalMilliseconds;
                if (elapsed + pbTimer.Step > pbTimer.Maximum)
                    pbTimer.Value = pbTimer.Maximum;
                else
                    pbTimer.PerformStep();

            }
        }

        private void tsbStayOnTop_CheckedChanged(object sender, EventArgs e)
        {
            TopMost = tsbStayOnTop.Checked;
        }

        private void bRefreshComments_Click(object sender, EventArgs e)
        {
            string HTML = GetHTML(@"http://www.esl.eu/de/cs/5on5/mr12/ladder/match/10061445/");
            HtmlAgilityPack.HtmlDocument d = new HtmlAgilityPack.HtmlDocument();
            d.LoadHtml(HTML);

            

            string htmlnew = string.Empty;
            HtmlNodeCollection styles = d.DocumentNode.SelectNodes(@"//link[@type=""text/css""] | //style[@type=""text/css""]");
            foreach (HtmlNode n in styles)
            {
                htmlnew += n.WriteTo();
            }
            htmlnew += d.DocumentNode.SelectSingleNode(@"//a[@name=""comments""]/following-sibling::table").WriteTo();

            HtmlNodeCollection posts = d.DocumentNode.SelectNodes(@"//a[@name=""comments""]/following-sibling::table/tr[position()>2]/td[2]");
            if (posts != null)
            {
                foreach (HtmlNode n in posts)
                {
                    //string text = n.InnerHtml;
                    //Match m = Regex.Match(text, @"([^ \n>]*?):(\d{3,6}).*?(?:pw|passwort|password|passwort ist)[:= ]+([^ \r\n<]*)", RegexOptions.Singleline | RegexOptions.IgnoreCase);
                    string text = Regex.Replace(n.WriteTo(), @"([^ \n>]*?):(\d{3,6})(.*?(?:pw|passwort|password)[:= ]+""*([^ \r\n<""]*))*", @"<a href=""hlsw://$4@$1:$2"">$1:$2</a>$3", RegexOptions.Singleline | RegexOptions.IgnoreCase);
                    htmlnew = htmlnew.Replace(n.WriteTo(), text);
                }
            }

            


            //don't allow new windows
            htmlnew = htmlnew.Replace("target=\"_blank\"", "");
            //fix online status icon
            htmlnew = htmlnew.Replace(@"var imgfile=""/interface/online_check/", @"var imgfile=""http://www.esl.eu/interface/online_check/");

            htmlnew = Regex.Replace(htmlnew, @"(<span.*?>)comments.*?\(\s*(\d+)\s*\).*?</span>", @"$1$2 comments <a href=""/refreshpage.action""><h3>(refresh)</h3></a></span>", RegexOptions.Singleline | RegexOptions.IgnoreCase);
            //htmlnew = Regex.Replace(htmlnew, @"([^ \n>]*?):(\d{3,6}).*?(?:pw|passwort|password|passwort ist)[:= ]+([^ \r\n<]*)", @"<a href=""hlsw://$3@$1:$2"">$0</a>", RegexOptions.Singleline | RegexOptions.IgnoreCase);

            htmlnew = Regex.Replace(htmlnew, @"/\* Formatierung der Seite \*/.*?/\* Hier kann ein umlaufender Rand um die gesamte Webseite erzeugt werden \*/", "", RegexOptions.Singleline);

            webBrowser2.DocumentText = htmlnew;
            /*HtmlNodeCollection comments = d.DocumentNode.SelectNodes(@"//a[@name=""comments""]/following-sibling::table/tr[position()>2 and position() < last()-1]");
            if (comments != null)
            {
                foreach(HtmlNode n in comments)
                {
                    rtbComments.AppendText(n.SelectSingleNode("td[1]/a[@href]").InnerText + ":\n");
                    rtbComments.AppendText(n.SelectSingleNode("td[2]").InnerText + Environment.NewLine);
                }
            }*/
        }

        private void rtbComments_LinkClicked(object sender, LinkClickedEventArgs e)
        {
            Process.Start(e.LinkText);
        }

        private void webBrowser2_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            if (e.Url.ToString() != "about:blank")
            {
                if (e.Url.ToString() == "about:blank/refreshpage.action")
                    bRefreshComments_Click(sender, new EventArgs());
                else
                {
                    Process.Start(e.Url.ToString().Replace("about:blank", "http://esl.eu"));
                    e.Cancel = true;
                }
                
            }
        }

        private void webBrowser2_NewWindow(object sender, CancelEventArgs e)
        {
            e.Cancel = true;
        }

        private void tabControl1_Selected(object sender, TabControlEventArgs e)
        {
            if (e.Action == TabControlAction.Selected && e.TabPage == tabMatchComments)
            {
                if (webBrowser2.DocumentText == string.Empty)
                    bRefreshComments_Click(sender, new EventArgs());
                webBrowser2.Select();
            }
        }

        private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
        {
#if DEBUG
            return;
#endif
            if ((e.TabPage == tabMatchComments || e.TabPage == tabPreMatch) && m_Matchlink == string.Empty)
                e.Cancel = true;
        }
    }

 
}